package com.tencreat.service.account.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.extra.cglib.CglibUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.tencreat.common.core.HttpResult;
import com.tencreat.common.core.domain.entity.SysDept;
import com.tencreat.common.core.domain.entity.SysRole;
import com.tencreat.common.core.domain.entity.SysUser;
import com.tencreat.common.core.domain.model.ReqIdParam;
import com.tencreat.common.core.domain.model.ReqIdsParam;
import com.tencreat.common.enums.BalanceBusinessType;
import com.tencreat.common.enums.UserType;
import com.tencreat.common.enums.mall.AllEnum;
import com.tencreat.common.exception.CustomException;
import com.tencreat.domain.mall.MallCategory;
import com.tencreat.quartz.util.GpsDistanceUtils;
import com.tencreat.common.utils.SecurityUtils;
import com.tencreat.common.utils.StringUtils;

import com.tencreat.common.utils.uuid.IdUtils;

import com.tencreat.domain.account.MallStore;
import com.tencreat.domain.account.MallUser;
import com.tencreat.domain.account.dto.AccountRegisterDTO;
import com.tencreat.domain.account.dto.MallStoreDTO;
import com.tencreat.domain.account.dto.MallSupplierRequDTO;
import com.tencreat.domain.account.vo.MallStoreRespVo;
import com.tencreat.domain.account.vo.MallStoreStaticsVo;
import com.tencreat.domain.mall.BalanceChange;
import com.tencreat.domain.mall.dto.MallGoodsSearchDTO;
import com.tencreat.domain.mall.dto.MallStoreAuditDTO;
import com.tencreat.domain.mall.vo.MallGoodsDetailsVO;
import com.tencreat.domain.mall.vo.MallGoodsListVO;
import com.tencreat.domain.mall.vo.MallStoreGoodsVO;
import com.tencreat.domain.mall.vo.MallStoreScanInfoVO;
import com.tencreat.mapper.account.MallStoreMapper;
import com.tencreat.mapper.system.SysDeptMapper;
import com.tencreat.service.account.*;
import com.tencreat.service.mall.IBalanceChangeService;
import com.tencreat.service.mall.IMallCategoryService;
import com.tencreat.service.system.ISysMessageService;
import com.tencreat.service.system.ISysRoleService;
import com.tencreat.service.system.ISysUserService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 店铺Service业务层处理
 *
 * @author tencreat
 * @date 2021-08-13
 */
@Service
public class MallStoreServiceImpl extends ServiceImpl<MallStoreMapper, MallStore> implements IMallStoreService {

    @Autowired
    private IMallSystemService mallSystemService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private AccountLoginCheckServiceImpl accountLoginCheckService;
    @Autowired
    private ISysRoleService roleService;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private IMallRegionService regionService;
    @Autowired
    private ISysMessageService sysMessageService;
    @Autowired
    private SysDeptMapper deptMapper;
    @Autowired
    private IMallUserService mallUserService;
    @Autowired
    private IBalanceChangeService balanceChangeService;

    @Autowired
    private IMallCategoryService categoryService;

    /**
     * 查询店铺
     *
     * @param id 店铺ID
     * @return 店铺
     */
    @Override
    public MallStore selectMallStoreById(ReqIdParam id) {
        MallStore mallStore = baseMapper.selectStoreById(id.getId());
        //根据省市区获取详情信息
        if (mallStore != null) {
            String name = regionService.getNameBycounty(mallStore.getCounty());
            mallStore.setAreasName(name);
        }
        return mallStore;
    }

    /**
     * 查询店铺
     *
     * @param id 店铺ID
     * @return 店铺
     */
    @Override
    public MallStore selectMallStoreById(Long id) {
        return baseMapper.selectById(id);
    }

    /**
     * 查询店铺列表
     *
     * @param mallStore 店铺
     * @return 店铺
     */
    @Override
    public List<MallStore> selectMallStoreList(MallStore mallStore) {
        return baseMapper.selectList(Wrappers.query(mallStore));
    }

    /**
     * 新增店铺
     *
     * @param mallStoreVO 店铺
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResult<String> insertMallStore(MallStoreDTO mallStoreVO) {
        // 根据uuid查询店铺
        MallUser one = mallUserService.lambdaQuery().eq(MallUser::getUuid, mallStoreVO.getUuid()).one();
        if (one == null) {
            throw new CustomException("该用户不存在");
        }
        mallStoreVO.setMobile(one.getMobile());
//		mallStoreVO.setCode("http://youmaiyoumai.mallStore/"+one.getUserId());//二维码
        // 新增店铺
        MallStore mallStore = CglibUtil.copy(mallStoreVO, MallStore.class);
        //mallStore.setStoreName(mallStoreVO.getUsername());
        mallStore.setApprovalStatus(0);
        mallStore.setStatus(0);
        mallStore.setCreateTime(LocalDateTime.now());
        save(mallStore);
        // 审核店铺
        MallStoreAuditDTO dto = new MallStoreAuditDTO();
        dto.setId(mallStore.getId());
        dto.setType(1);
        dto.setPassword(mallStoreVO.getPassword());
        audit(dto);
        return HttpResult.ok("新增成功");
    }

    public SysUser insertSysUser(MallStore mallStore, String pass) {
        SysUser user = new SysUser();
        user.setUserName(mallStore.getMobile());
        user.setPhonenumber(mallStore.getMobile());
        user.setNickName(mallStore.getUsername());
        user.setCreateTime(LocalDateTime.now());
        // 账号绑定固定的供应商角色
        SysRole sysRole = roleService.selectRoleByRoleStore("mallStore");
        if (sysRole == null) {
            throw new CustomException("没有找到店铺角色");
        }
        Long[] roleIds = {sysRole.getRoleId()};
        user.setRoleIds(roleIds);
        user.setStore(1);
        user.setPassword(SecurityUtils.encryptPassword(pass));
        // 注册账号
        userService.insertUser(user);


        //创建一个属于本人的部门
        SysDept sysDept = new SysDept();
        sysDept.setAncestors("0");
        sysDept.setDeptName(user.getNickName());
        sysDept.setOrderNum("0");
        sysDept.setLeader(user.getNickName());
        sysDept.setPhone(user.getPhonenumber());
        sysDept.setCreateTime(LocalDateTime.now());
        sysDept.setUpdateTime(LocalDateTime.now());
        sysDept.setTenantId(user.getUserId());
        deptMapper.insertDept(sysDept);

        SysUser deptUser = new SysUser();
        deptUser.setUserId(user.getUserId());
        deptUser.setTenantId(user.getUserId());
        deptUser.setDeptId(sysDept.getDeptId());
        userService.updateUserStatus(deptUser);
        return user;
    }

    private void insertAccountLoginCheck(MallStoreDTO mallStoreVO) {
        AccountRegisterDTO accountRegisterPO = new AccountRegisterDTO();
        accountRegisterPO.setPassword(mallStoreVO.getPassword());
        accountRegisterPO.setPhone(mallStoreVO.getMobile());
        accountRegisterPO.setUsername(mallStoreVO.getMobile());
        accountRegisterPO.setReferrerUuid(AllEnum.SUPER_UUID);
        accountRegisterPO.setCode(AllEnum.SUPER_CODE);
        accountRegisterPO.setUserType(UserType.ORDINARY.getValue());
        accountLoginCheckService.register(accountRegisterPO);
    }

    /**
     * 审核店铺
     *
     * @param id     店铺ID
     * @param passed 是否审核通过
     * @return 结果
     */
    @Override
    @Deprecated
    public HttpResult<String> auditMallStore(ReqIdParam id, Boolean passed) {
        MallStore mallStore = baseMapper.selectById(id.getId());
        if (mallStore == null || !mallStore.getApprovalStatus().equals(0) || passed == null) {
            return HttpResult.ok("无法修改");
        }
        if (passed) {
            mallStore.setApprovalStatus(1);
            sysMessageService.auditMallStore(mallStore.getMobile(), mallSystemService.selectMallSystemByName("供应商审核成功消息").getKeyValue());
        } else {
            mallStore.setApprovalStatus(2);
        }
        baseMapper.updateById(mallStore);
        return HttpResult.ok("修改成功");
    }

    /**
     * 描述信息  重置密码
     *
     * @Author yaoruiqi
     * @Date: 2023/10/10 11:29
     */
    @Override
    public HttpResult<Boolean> password(MallSupplierRequDTO mallStore) {
        SysUser user = userService.selectUserById(mallStore.getUserId());
        user.setPassword(SecurityUtils.encryptPassword(mallStore.getPassword()));

/*		AccountLoginCheck one = accountLoginCheckService.lambdaQuery().eq(AccountLoginCheck::getPhone, user.getPhonenumber()).one();
		one.setPassword(Md5Utils.hash(mallStore.getPassword()));
		accountLoginCheckService.updateAccountLoginCheck(one);

		 //账号绑定固定的供应商角色
		SysRole sysRole = roleService.selectRoleByRoleSupplier("supplier");
		if (sysRole == null) {
			throw new CustomException("没有找到供应商角色");
		}
		Long[] roleIds = { sysRole.getRoleId() };
		user.setRoleIds(roleIds);*/
        return HttpResult.ok(userService.updateUserStatus(user) > 0);
    }

    /**
     * 修改店铺
     *
     * @param mallStore 店铺
     * @return 店铺
     */
    @Override
    public HttpResult<String> updateMallStore(MallStore mallStore) {
        mallStore.setUpdateTime(LocalDateTime.now());
        //查到父分类
        MallCategory category = categoryService.lambdaQuery().eq(MallCategory::getId, mallStore.getPid()).one();
        //查到本分类
        MallCategory one = categoryService.lambdaQuery().eq(MallCategory::getId, mallStore.getCategoryId()).one();
//        if (one != null) {
//            mallStore.setClassify(String.valueOf(one.getType()));
//        }
        baseMapper.updateById(mallStore);
        return HttpResult.ok("修改成功");
    }

    /**
     * 批量删除店铺
     *
     * @param ids 需要删除的店铺ID
     * @return 结果
     */
    @Override
    public int deleteMallStoreByIds(ReqIdsParam ids) {
        for (Long id : ids.getId()) {
            MallStore mallStore = baseMapper.selectById(id);
            MallUser one = mallUserService.lambdaQuery().eq(MallUser::getMobile, mallStore.getMobile()).one();
            one.setStore(Long.valueOf(AllEnum.StoreGoods.NO.getType()));
            mallUserService.updateById(one);
        }
        return baseMapper.deleteBatchIds(ids.getId());
    }

    /**
     * 删除店铺信息
     *
     * @param id 店铺ID
     * @return 结果
     */
    @Override
    public int deleteMallStoreById(ReqIdParam id) {
        return baseMapper.deleteById(id.getId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void audit(MallStoreAuditDTO dto) {
        String key = "mall_store_audit_" + dto.getId();
        RLock lock = redissonClient.getLock(key);
        lock.lock();
        try {
            MallStore mallStore = lambdaQuery().eq(MallStore::getId, dto.getId()).one();
            if (mallStore == null || mallStore.getApprovalStatus() != 0) {
                throw new CustomException("该数据已操作，请刷新后重试！");
            }
            // 校验
//            int count = lambdaQuery().eq(MallStore::getStoreName, mallStore.getStoreName()).eq(MallStore::getApprovalStatus, 1).count();
//            if (count > 0) {
//                throw new CustomException("已存在相同店铺名称");
//            }
            MallUser mallUser = mallUserService.lambdaQuery().eq(MallUser::getMobile, mallStore.getMobile()).one();

            // 审核通过
            if (dto.getType() == 1) {
                // 创建用户密码
                String password = RandomUtil.randomString(6);
                if (StringUtils.isNotEmpty(dto.getPassword())) {
                    password = dto.getPassword();
                }
                // 创建一个后台账号
                SysUser user = insertSysUser(mallStore, password);
                // 修改审核状态
                LambdaUpdateChainWrapper<MallStore> wrapper = lambdaUpdate().eq(MallStore::getId, mallStore.getId())
                        .set(MallStore::getUserId, user.getUserId())
                        .set(MallStore::getAccount, user.getUserName())
                        .set(MallStore::getStatus, 0)
                        .set(MallStore::getApprovalStatus, dto.getType());
                if (mallUser != null) {
                    wrapper.set(MallStore::getUuid, mallUser.getUuid());
                    mallUser.setStore(Long.valueOf(AllEnum.StoreGoods.YES.getType()));
                    mallUser.setUserId(user.getUserId());
                    mallUserService.lambdaUpdate().eq(MallUser::getId, mallUser.getId())
                            .set(MallUser::getStore, mallUser.getStore())
                            .set(MallUser::getUserId, mallUser.getUserId())
                            .update();
                }
                wrapper.update();
                // 发送信息
                sysMessageService.smsStoreApproved(user.getPhonenumber(), user.getUserName(), password);

            }
            // 驳回
            else {
                // 修改审核状态
                lambdaUpdate().eq(MallStore::getId, mallStore.getId()).set(MallStore::getApprovalStatus, 2).update();

            }
        } catch (Exception e) {
            throw e;
        } finally {
            lock.unlock();
        }
    }


    @Override
    public synchronized int generateUUID() {
        while (true) {
            int uuid = IdUtils.generateUUID();
            Integer oldUUID = IdUtils.idCache.get(uuid);
            if (oldUUID == null) {
                int count = lambdaQuery().eq(MallStore::getUuid, uuid).count();
                if (count == 0) {
                    IdUtils.idCache.put(uuid, uuid);
                    return uuid;
                }
            }
        }
    }

    @Override
    public MallStoreStaticsVo storeStatics() {
        MallStoreStaticsVo mallStoreStaticsVo = new MallStoreStaticsVo();
        // 获取今天的时间
        LocalDateTime beginOfDay = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
        String Day = DateUtil.format(beginOfDay, "yyyyMMdd");
        // 店铺总数
        Integer totalCount = lambdaQuery().count();
        // 昨日新增店铺总数
        Integer lastTotalCount = lambdaQuery().apply("date_format(create_time,'%Y%m%d') = " + "'" + Day + "'").count();
        // 禁用总数
        Integer disableCount = lambdaQuery().eq(MallStore::getStatus, 1).count();
        // 昨日禁用数
        Integer lastDisableCount = lambdaQuery().eq(MallStore::getStatus, 1).apply("date_format(create_time,'%Y%m%d') = " + "'" + Day + "'").count();
        // 待审核总数
        Integer auditCount = lambdaQuery().eq(MallStore::getApprovalStatus, 0).count();
        // 昨日新增待审核总数
        Integer lastAuditCount = lambdaQuery().eq(MallStore::getApprovalStatus, 0).apply("date_format(create_time,'%Y%m%d') = " + "'" + Day + "'").count();
        // 货款总数
        BigDecimal amount = userService.querySupplierEarnings();
        // 昨日新增货款总数
        List<BalanceChange> list = balanceChangeService.lambdaQuery().eq(BalanceChange::getBusinessType, BalanceBusinessType.ORDER_CONFIRM)
                .apply("date_format(create_time,'%Y%m%d') = " + "'" + Day + "'")
                .list();
        double lastAmount = 0;
        if (list != null) {
            lastAmount = Lists.transform(list, l -> l.getChangAmount().doubleValue()).stream().mapToDouble(Double::doubleValue).sum();
        }

        mallStoreStaticsVo.setAmount(amount != null ? amount : BigDecimal.ZERO);
        mallStoreStaticsVo.setLastAmount(BigDecimal.valueOf(lastAmount));
        mallStoreStaticsVo.setAuditCount(auditCount != null ? auditCount : 0);
        mallStoreStaticsVo.setLastAuditCount(lastAuditCount != null ? lastAuditCount : 0);
        mallStoreStaticsVo.setDisableCount(disableCount != null ? disableCount : 0);
        mallStoreStaticsVo.setLastDisableCount(lastDisableCount != null ? lastDisableCount : 0);
        mallStoreStaticsVo.setLastTotalCount(lastTotalCount != null ? lastTotalCount : 0);
        mallStoreStaticsVo.setTotalCount(totalCount != null ? totalCount : 0);

        return mallStoreStaticsVo;
    }

    @Override
    public IPage<MallStoreRespVo> queryAll(Page<MallStore> page, MallStore mallStore) {
        if (mallStore.getSortDesc() != null && mallStore.getSortStr() != null) {
            if (mallStore.getSortDesc().equals("descending")) {
                mallStore.setSortDesc("desc");
            } else {
                mallStore.setSortDesc("asc");
            }
        }
        return baseMapper.queryAll(page, mallStore);
    }

    @Override
    public MallStoreScanInfoVO selectScanMallStoreById(Long id) {
        MallStore mallStore = baseMapper.selectById(id);
        MallStoreScanInfoVO mallStoreScanInfoVO = new MallStoreScanInfoVO();
        BeanUtils.copyProperties(mallStore, mallStoreScanInfoVO);
        return mallStoreScanInfoVO;
    }


    /**
     * 描述信息  根据商户id查找商户手机号
     *
     * @Author yaoruiqi
     * @Date: 2023/10/13 10:05
     */
    @Override
    public HttpResult<String> getMobileById(Long id) {
        MallStore mallStore = baseMapper.getMobileById(id);
        return HttpResult.ok(mallStore.getMobile());
    }

    @Override
//	public IPage<MallGoodsListVO> apiStoreList(MallGoodsSearchDTO mallGoodsSearchPo,Page<MallStore> mallGoodsIPage ) {
    public IPage<MallGoodsListVO> apiStoreList(IPage<MallStore> mallGoodsIPage, MallGoodsSearchDTO mallGoodsSearchPo) {

        IPage<MallStore> page = baseMapper.getApiList(mallGoodsIPage, mallGoodsSearchPo);

        return page.convert(item -> {
            MallGoodsListVO mallGoodsListVO = new MallGoodsListVO();
            mallGoodsListVO.setId(item.getId());
            mallGoodsListVO.setCoverImg(item.getPhoto());
            mallGoodsListVO.setTitle(item.getStoreName());
            mallGoodsListVO.setStar(item.getStar());
            //mallGoodsListVO.setExpectCommoditySales((item.getExpectCommoditySales() == null ? BigDecimal.ZERO : item.getExpectCommoditySales()).intValue());
            mallGoodsListVO.setCommoditySales((item.getCommoditySales() == null ? BigDecimal.ZERO : item.getCommoditySales()).intValue());
            mallGoodsListVO.setIsHot(item.getIsHot());
//            mallGoodsListVO.setClassify(item.getClassify());
            return mallGoodsListVO;
        });
    }

    @Override
    public IPage<MallGoodsListVO> page(IPage<?> iPage, MallGoodsSearchDTO mallStore) {
        if (StringUtils.isEmpty(mallStore.getDimensionality())) {
            mallStore.setDimensionality("0");
        }
        if (StringUtils.isEmpty(mallStore.getLongitude())) {
            mallStore.setLongitude("0");
        }

        return baseMapper.page(iPage, mallStore);
    }

    @Override
    public Long selectStoreApprovalStatus(Long uuid) {
        return baseMapper.selectStoreApprovalStatus(uuid);
    }

    @Override
    public List<MallGoodsListVO> storeListTwo(ReqIdParam idParam) {
        Long id = idParam.getId();
        return baseMapper.storeListTwo(id);
    }

    @Override
    public MallGoodsDetailsVO storeInfo(ReqIdParam idParam) {
        if (StringUtils.isEmpty(idParam.getDimensionality())) {
            idParam.setDimensionality("0");
        }
        if (StringUtils.isEmpty(idParam.getLongitude())) {
            idParam.setLongitude("0");
        }
        return baseMapper.storeInfo(idParam.getId(), idParam.getDimensionality(), idParam.getLongitude());
    }

    @Override
    public List<MallStore> selectStoreByName(String storeName) {
        return baseMapper.selectStoreByName(storeName);
    }

    @Override
    public MallStore selectUserById(Long userId) {
        return baseMapper.selectUserById(userId);
    }

    @Override
    public HttpResult<MallStoreGoodsVO> category(Long userId) {
        return HttpResult.ok(baseMapper.category(userId));
    }


    private BigDecimal distance(String longitude1, String dimensionality1, String longitude2, String dimensionality2) {

        BigDecimal distance = BigDecimal.ZERO;
        // 距离计算
        // 根据经纬度  计算两点之间的直线距离
        if (StringUtils.isNotEmpty(dimensionality1) && StringUtils.isNotEmpty(longitude1)
                && StringUtils.isNotEmpty(longitude2) && StringUtils.isNotEmpty(dimensionality2)) {
            // m 为单位
            distance = GpsDistanceUtils.getDistance(Double.parseDouble(longitude1),
                    Double.parseDouble(dimensionality1),
                    Double.parseDouble(longitude2),
                    Double.parseDouble(dimensionality2), 2);

            if (distance.compareTo(new BigDecimal(1000)) > 0) {
                // 转换为km
                if (distance != null && distance.doubleValue() != 0) {
                    distance = distance.multiply(BigDecimal.valueOf(0.001)).setScale(2, BigDecimal.ROUND_HALF_UP);
                }
            }

            return distance;
        }
        return distance;

    }
}
